package com.happycat.controller.social;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.happycat.base.R;
import com.happycat.base.exception.RestApiException;
import com.happycat.social.dto.SocialTransDto;
import com.happycat.social.entity.SocialTrans;
import com.happycat.social.service.ISocialWxService;
import com.happycat.social.wx.WxPayOrderNotifyResult;
import com.happycat.utils.ObjectsUtil;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.jfinal.kit.StrKit;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author shenbin
 * @CreatedDate 2020-09-14
 * @Modified By:
 */
@RestController
@RequestMapping("/social/pay")
@Api(tags = "API-支付", value = "支付对接等")
@Slf4j
public class SocialPayController {

    @Autowired
    private ISocialWxService socialWxService;

    @ApiOperation(value = "充值", notes = "目前支持的支付方式:微信小程序支付，微信app支付")
    @PostMapping(value = "/recharge")
    public R<String> recharge(HttpServletRequest request, @RequestBody @Valid SocialTransDto socialTransDto){
        if(socialTransDto.getPayAmount()==null || socialTransDto.getPayAmount().compareTo(0.0) <= 0){
            R.fail("支付金额不能小于0");
        }
        if(socialTransDto.getReceiveAmount()==null || socialTransDto.getPayAmount().compareTo(0.0) <= 0){
            R.fail("充值猫粮数量不能小于0");
        }

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        socialTransDto.setIp(ip);

        return R.success(socialWxService.wxPay(socialTransDto));
    }

    @ApiOperation(value = "微信支付结果查询", notes = "仅支持充值流水状态查询")
    @GetMapping(value = "/wxPayStatus/{transId}")
    @ApiImplicitParam(name = "transId", value = "充值流水id", required = true)
    public R<SocialTrans> wxPayStatus(HttpServletRequest request, @PathVariable Long transId){
        ObjectsUtil.requireNonNull(transId, "充值流水不能为空");
        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        return R.success(socialWxService.wxPayStatus(transId, ip));
    }

    /**
     * 异步通知
     */
    @RequestMapping(value = "/payNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "微信支付异步通知", notes = "微信异步调用")
    public String payNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);

        WxPayOrderNotifyResult result = BeanUtil.toBean(params, WxPayOrderNotifyResult.class);

        log.info("微信支付结果通知:{}", JSONUtil.toJsonStr(result));

        String returnCode = params.get("return_code");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey(), SignType.HMACSHA256)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                try {
                    synchronized (result.getOut_trade_no()){
                        // 更新流水信息等
                        boolean isOK = socialWxService.wxPayNotify(result);
                        if(!isOK){
                            throw new RestApiException(R.fail("处理失败"));
                        }
                    }
                    // 发送通知等
                    Map<String, String> xml = new HashMap<String, String>(2);
                    xml.put("return_code", "SUCCESS");
                    xml.put("return_msg", "OK");
                    return WxPayKit.toXml(xml);
                } catch (Exception e) {
                    log.error("处理失败:{}", e.getMessage());
                    Map<String, String> xml = new HashMap<String, String>(2);
                    xml.put("return_code", "FAIL");
                    xml.put("return_msg", "FAIL");
                    return WxPayKit.toXml(xml);
                }
            }
        }else {
            log.error("验证签名失败...");
            Map<String, String> xml = new HashMap<String, String>(2);
            xml.put("return_code", "FAIL");
            xml.put("return_msg", "验证签名失败");
            return WxPayKit.toXml(xml);
        }
        return null;
    }

}
